﻿'=======================================================================================================================================
'
' Programmer:       Michael Williams
'
'
'
'
'
'
'
'=======================================================================================================================================
' Dependencies:
'=======================================================================================================================================
'               1) Add Speech to Visual Studio
'               Reference the System.Speech assembly from the application
'               Project | Add Reference...
'               In the Add Reference window, on the .NET tab, scroll until you find System.Speech and select it, and then click OK.    
'
'               In your Visual Studio project, add a imports statement for each System.Speech namespace that you want to access. 
'               For example, if you want to work with speech synthesis, enter the following imports statement
'               imports System.Speech.Synthesis; 
'
'=======================================================================================================================================
' Considerations:
'=======================================================================================================================================
'
'       VOICES IN 64bit Versions:
'           In Win64 and .NET. .NET apps (by definition) run as 64 bit apps on a 64-bit OS, and 32 bit apps on a 32-bit OS. 
'           However, you can't load a 32-bit DLL into a 64-bit app. All the Microsoft TTS engines ship in both 64-bit and 32-bit versions, 
'           but the Scansoft engines apparently only ship in 32-bit versions. Therefore, on a 64-bit application, you can only load the Microsoft 
'           TTS engines, and not the Scansoft engines. And, therefore, if you mark your .NET app as 32-bit only, you can load both engines, and 
'           you see all your voices. – Eric Brown Jul 20 '10 at 17:12
'           Info Source: http://stackoverflow.com/questions/3208617/speechsynthesizer-doesnt-get-all-installed-voices'
'
'=======================================================================================================================================

' TODOMW: Implement Graphic head that talks via MS Speech talking face. To be used in Form GUI. This will be implemented with speech events.
'
'
'
'========================================================================================================================================
' EXAMPLE CODE:
'========================================================================================================================================
' NOTE: Test only. Notice below example of Auto-Implemented Property.
'//Public Property strTitleString As String
' NOTE:   See simple way of declaring a property if no validation code required.
'           This does the same as below only with one line of code.
'  NOTE: Test only.
'//*Dim TitleStringMW As String
'Property TitleMW As String
'    Get
'        Return TitleStringMW
'    End Get
'    Set(ByVal value As String)
'        TitleStringMW = value
'    End Set
'*//End Property
'
'
'========================================================================================================================================


' Compiler Options:
Option Explicit On
Option Strict On
Option Infer Off

'Namespace import for Speech assembly
Imports System.Speech.Synthesis




Public Class SpeechMW
    Dim WithEvents m_oMSSpeechMW As New SpeechSynthesizer()
    Dim m_Prompt As System.Speech.Synthesis.Prompt

    ' TODOMW:   Attach events to be used for the SpeechSynthesizer object.
    '           This will not be required for the TalkingSpeller project but will be handy for using DLL in other projects.
    '           See below for events that have been included at the moment.
    '
    '===================
    ' Event Interests.
    '===================
    Public Event SpeakCompleted As EventHandler(Of SpeakCompletedEventArgs)

    Public Sub New()
        ' NOTE: The reason you must call the New method of the base class is that the base class
        '       might have its own constructor, which can't be called directly.
        MyBase.New()

        ' Create the speech object.
        m_oMSSpeechMW = New SpeechSynthesizer

        ' Register for events.
        AddHandler m_oMSSpeechMW.SpeakCompleted, AddressOf SpeachComplete


        Console.ReadLine()
    End Sub

    Private Sub SpeachComplete(sender As Object, e As SpeakCompletedEventArgs)
        ' TODOMW: Example only. Not implemented yet. But works.
        '//MsgBox("Speach Done in SpeechMW class.")
    End Sub


    Public Function SayStop() As Boolean
        ' Stop the speaking of any current voice.
        Dim result As Boolean
        If (m_Prompt) Is Nothing Then
            result = False
        Else
            m_oMSSpeechMW.SpeakAsyncCancel(m_Prompt)
            result = True
        End If

        Return result
    End Function
    Public Function SayString(ByVal textToSpeak As String) As Boolean
        'Generates speech output asynchronously from a string.

        Dim result As Boolean

        ' TODOMW: Check if not null before test length. Otherwise exception.
        If textToSpeak = Nothing Then
            result = False
        ElseIf textToSpeak.Length > 0 Then
            m_Prompt = m_oMSSpeechMW.SpeakAsync(textToSpeak)
            result = True
        Else
            result = False
        End If

        Return result
    End Function

    Public Function SpellString(ByVal textToSpell As String) As Boolean
        'Spells the text asynchronously from a given string.

        Dim result As Boolean
        Dim ch As Char

        ' TODOMW: Check if not null before test length. Otherwise exception thrown.
        If textToSpell = Nothing Then
            result = False
        ElseIf textToSpell.Length > 0 Then
            result = True
            For Each ch In textToSpell
                SayString(ch)
            Next
        Else
            result = False
        End If

        Return result
    End Function

    Public Function GetInstalledVoices() As String

        ' TODOMW: Test only. Expand true functionality.

        ' NOTE:  In Win64 and .NET. .NET apps (by definition) run as 64 bit apps on a 64-bit OS, and 32 bit apps on a 32-bit OS. 
        '       However, you can't load a 32-bit DLL into a 64-bit app. All the Microsoft TTS engines ship in both 64-bit and 32-bit versions, 
        '       but the Scansoft engines apparently only ship in 32-bit versions. Therefore, on a 64-bit application, you can only load the Microsoft 
        '       TTS engines, and not the Scansoft engines. And, therefore, if you mark your .NET app as 32-bit only, you can load both engines, and 
        '       you see all your voices. – Eric Brown Jul 20 '10 at 17:12
        '       Info Source: http://stackoverflow.com/questions/3208617/speechsynthesizer-doesnt-get-all-installed-voices

        'NOTE:  The method GetInstalledVoices returns the collection of speech synthesis (text-to-speech) voices that are currently 
        '       installed on the system.

        Dim voices As String = ""

        For Each v As Speech.Synthesis.InstalledVoice In m_oMSSpeechMW.GetInstalledVoices
            voices = voices & vbCr & v.VoiceInfo.Name
        Next

        Return voices
    End Function


End Class
